
#include <stdint.h>
#include "BootDefine.h"
#include "BootBsp.h"
#include "SoftCrc.h"

#define PPP_FRAME_FLAG		( 0x7E )	 /* ±êÊ¶×Ö·û */
#define PPP_FRAME_ESC		( 0x7D )	/* ×ªÒå×Ö·û */
#define PPP_FRAME_ENC		( 0x20 )	/* ±àÂë×Ö·û */

#define PACK_MAX_SIZE		(2048 + 128)

static uint8_t rxBuffer[PACK_MAX_SIZE+128];
static volatile uint8_t frameComplete;
static Pack_T* rxPack = (Pack_T*)rxBuffer;
static volatile uint8_t rxState;

volatile uint32_t rxCount;

static void Transfer_DoRxPack(uint8_t ch){
	switch(rxState){
	case 0:{
		if(ch == PPP_FRAME_FLAG){
			rxState = 1;
		}
	}
	break;
	case 1:{
		if(ch == 0xFF){
			rxState = 2;
		}
		else{
			rxState = 0;
		}
	}
	break;
	
	case 2:{
		if(ch == 0x03){
			rxState = 3;
			rxPack->len = 0;
		}
		else{
			rxState = 0;
		}
	}
	break;
	
	case 3:{
		if(ch == PPP_FRAME_FLAG){
			frameComplete = 1;
			rxState = 0;
			break;
		}
		
		if(ch == PPP_FRAME_ESC){
			rxState = 4;
		}
		else
		if(rxPack->len < PACK_MAX_SIZE){
			rxPack->data[rxPack->len++] = ch;
		}
		else{
			rxState = 5;
		}
	}
	break;
	
	case 4:{
		rxState = 3;
		if(rxPack->len < PACK_MAX_SIZE){
			rxPack->data[rxPack->len++] = ch ^ PPP_FRAME_ENC;
		}
		else{
			rxState = 5;
		}
	}
	break;
	
	}
}

int Transfer_WaitConnect(uint32_t waittime){
	volatile uint32_t t1 = Bsp_Tick();
	
	while(1){
		Bsp_Seed();
		if(frameComplete){
			return 0;
		}
		if(BSP_CheckPlug()){
			return 1;
		}
		if((Bsp_Tick()-t1) > waittime){
			break;
		}
	}
	return -1;
}


void Transfer_RxCallback(uint8_t * rx, uint16_t len){
	uint32_t i;
	for(i = 0; i < len; i++){
		Transfer_DoRxPack(rx[i]);
	}
}

int Transfer_InPack(Pack_T** pack, uint32_t waittime){	
	uint32_t t1 = Bsp_Tick();
	
	while(1){
		Bsp_Seed();
		if(frameComplete){
			break;
		}
		if((Bsp_Tick()-t1) > waittime){
			return -3;
		}
	}
	frameComplete = 0;
	if(rxPack->len < 3){
		return -1;
	}
	uint16_t crc1 = crc16(rxPack->data, rxPack->len - 2);
	uint16_t crc2 = ((uint16_t)rxPack->data[rxPack->len - 1] << 8) | rxPack->data[rxPack->len - 2];
	if(crc1 != crc2){
		return -2;
	}
	rxPack->len -= 2;
	*pack = rxPack;
	return 0;
}

static void Transfer_SendCode(uint8_t ch){
	if(ch == PPP_FRAME_FLAG || ch == PPP_FRAME_ESC){
		Bsp_SendByte(PPP_FRAME_ESC);
		Bsp_SendByte(ch ^ PPP_FRAME_ENC);
	}
	else{
		Bsp_SendByte(ch);
	}
}

static uint16_t Transfer_SendCodeCrc(uint16_t crc, uint8_t ch){
	Transfer_SendCode(ch);
	return crc16_byte(crc, ch);
}
void Transfer_OutPack(Pack_T * pack){
	uint32_t i;
	uint16_t crc = 0;
	
	Bsp_SendByte(PPP_FRAME_FLAG);
	Bsp_SendByte(0xFF);
	Bsp_SendByte(0x03);
	
	for(i = 0; i < pack->len; i++){
		crc = Transfer_SendCodeCrc(crc, pack->data[i]);
	}
	Transfer_SendCode(crc);
	Transfer_SendCode(crc >> 8);
	Bsp_SendByte(PPP_FRAME_FLAG);
	Bsp_Flush();
}

void Transfer_Reset(void){
	rxState = 0;
	frameComplete = 0;
	rxCount = 0;
}

void Transfer_Init(void){
	rxState = 0;
	frameComplete = 0;
}


